package com.joymedia.thor;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.builder.ConfigBuilder;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.fill.Column;
import com.baomidou.mybatisplus.generator.fill.Property;
import com.joymedia.thor.utils.Inflector;
import org.jetbrains.annotations.NotNull;

import java.io.File;
import java.util.Arrays;
import java.util.Collections;
import java.util.Map;

/**
 * @author XSH
 */
public class CodeGenerator {
    public static void main(String[] args) {
        PackageConfig packageConfig = packageConfig();
        new AutoGenerator(mysqlDataSourceConfig())
            .global(globalConfig())
            .packageInfo(packageConfig)
            .strategy(strategyConfig())
            .template(templateConfig())
            .injection(injectionConfig())
            .execute();
    }

    ///**
    // * H2数据源配置
    // */
    //private DataSourceConfig h2DataSourceConfig() throws SQLException {
    //    DataSourceConfig dataSourceConfig = new DataSourceConfig
    //        .Builder("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;CASE_INSENSITIVE_IDENTIFIERS=TRUE", "sa", "")
    //        .build();
    //    //runScript(dataSourceConfig);
    //    return dataSourceConfig;
    //}

    //private void runScript(DataSourceConfig dataSourceConfig) throws SQLException {
    //    try (Connection connection = dataSourceConfig.getConn()) {
    //        InputStream inputStream = GeneratorTest.class.getResourceAsStream("/sql/init.sql");
    //        ScriptRunner scriptRunner = new ScriptRunner(connection);
    //        scriptRunner.setAutoCommit(true);
    //        scriptRunner.runScript(new InputStreamReader(inputStream));
    //    }
    //}

    /**
     * Mysql数据源配置
     */
    private static DataSourceConfig mysqlDataSourceConfig() {
        DataSourceConfig dataSourceConfig = new DataSourceConfig
            .Builder("jdbc:mysql://192.168.6.3:3306/thor?useUnicode=true&useSSL=false&characterEncoding=utf8", "root", "123456")
            .build();
        //runScript(dataSourceConfig);
        return dataSourceConfig;
    }

    /**
     * 全局配置
     */
    private static GlobalConfig globalConfig() {
        return new GlobalConfig.Builder()
            .outputDir(System.getProperty("user.dir"))
            .author("XSH")
            .openDir(true)
            .fileOverride()
            .build();
    }

    /**
     * 包配置
     */
    private static PackageConfig packageConfig() {
        return new PackageConfig.Builder().moduleName("test").parent("com.joymedia.thor").build();
    }

    /**
     * 策略配置
     */
    private static StrategyConfig strategyConfig() {
        return new StrategyConfig.Builder()
            .addInclude("employees") // 包含的表名
            .addTablePrefix("t_") //统一表前缀
            .entityBuilder()  // 实体相关配置
            .naming(NamingStrategy.underline_to_camel)
            .columnNaming(NamingStrategy.underline_to_camel)
            //.addSuperEntityColumns("id","create_time","update_time")
            //.superClass(BaseEntity.class)   //自动识别父类字段
            .addTableFills(new Column("create_time", FieldFill.INSERT))     //基于字段填充
            .addTableFills(new Property("updateTime", FieldFill.UPDATE))    //基于属性填充
            .controllerBuilder().enableHyphenStyle() //控制器相关配置
            .build();
    }

    /**
     * 自定义模板配置
     */
    private static TemplateConfig templateConfig() {
        return new TemplateConfig.Builder()  //激活所有默认模板
            //.entity("templates/MyEntityTemplate.java")  //覆盖默认模板的实体模板配置,使用自定义实体模板
            .build()
            .disable(TemplateType.XML); //禁用xml生成
        //上面代码等价于下面这里下面这里
        //return new TemplateConfig.Builder().entity("templates/MyEntityTemplate.java").controller().service().mapper().build();
    }

    /**
     * 自定义配置
     */
    private static InjectionConfig injectionConfig() {
        InjectionConfig injectionConfig = new InjectionConfig(Collections.singletonMap("abc", globalConfig().getAuthor() + "-mp")) {
            @Override
            public void prepareObjectMap(@NotNull Map<String, Object> objectMap) {
                objectMap.put("Inflector", Inflector.class);
            }
        };

        return injectionConfig.addFileOutConfig(Arrays.asList(
            new CustomFileOutConfig(".dto", "%sDTO", "/templates/dto.java.vm"),
            new CustomFileOutConfig(".dto", "%sRetrieveDTO", "/templates/retrieveDto.java.vm"),
            new CustomFileOutConfig(".dto.convert", "%sDTOConvert", "/templates/convert4DTO.java.vm"),
            new CustomFileOutConfig(".vo.convert", "%sVOConvert", "/templates/convert4VO.java.vm"),
            new CustomFileOutConfig(".vo", "%sVO", "/templates/vo.java.vm"),
            new CustomFileOutConfig(".vo", "%sRetrieveVO", "/templates/retrieveVo.java.vm"),
            new CustomFileOutConfig(".vo", "%sCreateVO", "/templates/createVo.java.vm"),
            new CustomFileOutConfig(".vo", "%sUpdateVO", "/templates/updateVo.java.vm")));
    }

    static class CustomFileOutConfig extends FileOutConfig {
        private final String packages;
        private final String filenamePattern;

        public CustomFileOutConfig(String packages, String filenamePattern, String templatePath) {
            super(templatePath);
            this.packages = packages;
            this.filenamePattern = filenamePattern;
        }

        @Override
        public File outputFile(@NotNull InjectionConfig injectionConfig, @NotNull TableInfo info) {
            ConfigBuilder config = injectionConfig.getConfig();
            return new File((config.getGlobalConfig().getOutputDir() + "/" + config.getPackageConfig().getParent() + "/" + packages)
                .replaceAll("\\.", "/") + "/" + String.format(filenamePattern, info.getEntityName()) + ".java");
        }
    }
}

